using System.Security.Policy;
using Crawler;

namespace Crawler.Tests
{
	/// <summary>
	/// Understands the CentralFactory and sets it up for Reference and Use by any class
	/// </summary>
	public class ScenarioFactory : IScenarioFactory
	{
		public static IScenarioFactory scenarioFactory = new ScenarioFactory();
		private ICentralFactory factory;
		private DownloadStore downloadStore;
		private UrlStack urlStack;
		private IFetcher fetcher;
		private Mapper mapper;
		private IDumper dumper;
		private IParserPool parserPool;
		private ICrawlerContext crawlerContext;

		private ScenarioFactory()
		{
			InitializeCrawlerContext();
			InitializeFactory();
			InitializeParser() ;
			InitializeDownloadStore() ;
			InitializeFetcher();
			InitializeDumper() ;
		}

		private void InitializeFetcher()
		{
			this.fetcher = new Fetcher(this.factory, this.crawlerContext );
			this.urlStack.UrlAddedToUrlStack += new UrlAddedToUrlStackHandler(fetcher.NotifyFetcherAboutUrlAdditionToUrlStack ) ;
		}

		private void InitializeDumper()
		{
			this.dumper = new Dumper(this.factory);
			this.mapper.EntryAddedToMapper += new EntryAddedToMapperHandler(dumper.NotifyDumperAboutEntryAdditionToMapper  ) ;
		}

		private void InitializeDownloadStore()
		{
			this.downloadStore.ReferenceAddedToDownloadStore +=
				new ReferenceAddedToDownloadStoreHandler(this.parserPool.NotifyWhenReferenceAddedToDownloadStore) ;
		}

		private void InitializeFactory()
		{
			this.factory = CentralFactory.centralFactory;
			this.urlStack = new UrlStack(this.crawlerContext);
			this.downloadStore = new DownloadStore(this.crawlerContext);
			this.mapper = new Mapper();
			this.factory.Add(downloadStore);
			this.factory.Add(urlStack);
			this.factory.Add(mapper);
		}

		private void InitializeParser()
		{
			this.parserPool = new ParserPool(1); 
		}

		private void SetCachePath(string path)
		{
			this.factory.AddCachePath(new ResourcePath(path) ) ;
		}

		private void SetDestinationPath(string path)
		{
			this.factory.Add(new ResourcePath(path)) ;
		}

		private void SetDomain(string domain)
		{
			this.factory.Add(domain) ; 
		}

		private void InitializeCrawlerContext()
		{
			this.crawlerContext = new CrawlerContext() ;
			this.crawlerContext.UrlStackEmpty = true; 
		}

		public void Initialize(string path, string destinationPath, string domain)
		{
			SetCachePath(path);
			SetDestinationPath(destinationPath);
			SetDomain(domain);
		
		}
		
		public void AddUrlToUrlStackAndTrigger(Url key, bool triggerFetcher)
		{
			this.urlStack.Add(key, triggerFetcher);
		}
		
		public void AddEntryToMapperAndTrigger(IKey key)
		{
			IPathExtractor pathExtractor = new PathExtractor(this.factory);
			this.mapper.Add(key, pathExtractor.ExtractAbsolutePathFromUrl(key));
		}

		public IResourceReference GetResourceWith(IKey key)
		{
			return this.downloadStore.GetResource(key);  
		}
	}
}
